#include "../Logs/LzcLog.h"

void TestUtil()
{
    std::cout << LzcLog::Util::GetTime() << std::endl;
    std::string dir = LzcLog::Util::GetDir("./Lzc/xxx/a.txt");
    std::cout << dir << std::endl;
    LzcLog::Util::CreateDir(dir);
}

void TestLogLevel()
{
    std::cout << LzcLog::LogLevel::LogLevelToString(LzcLog::LogLevel::Value::DEBUG) << std::endl;
    std::cout << LzcLog::LogLevel::LogLevelToString(LzcLog::LogLevel::Value::INFO) << std::endl;
    std::cout << LzcLog::LogLevel::LogLevelToString(LzcLog::LogLevel::Value::WARNING) << std::endl;
    std::cout << LzcLog::LogLevel::LogLevelToString(LzcLog::LogLevel::Value::ERROR) << std::endl;
    std::cout << LzcLog::LogLevel::LogLevelToString(LzcLog::LogLevel::Value::FATAL) << std::endl;
    std::cout << LzcLog::LogLevel::LogLevelToString(LzcLog::LogLevel::Value::OFF) << std::endl;
}

void TestLogMessage()
{
    LzcLog::LogMessage log_message(LzcLog::LogLevel::Value::INFO, "root", "main.cc", 9, "xxx");
}

void TestFormatter()
{
    // 构造测试日志消息（自定义字段）
    LzcLog::LogMessage test_msg(
        LzcLog::LogLevel::Value::INFO,        // %p 日志等级：INFO
        "user_login_logger",                  // %c 日志器名称
        __FILE__,                             // %f 文件名
        __LINE__,                             // %l 行号
        "用户张三登录成功, IP: 192.168.1.100" // 日志内容
    );

    std::cout << "===== 测试1: 默认格式 =====" << std::endl;
    LzcLog::LogFormatter default_formatter; // 默认格式: [%d{%H:%M:%S}][%t][%p][%c][%f:%l]%T%m%n
    std::cout << default_formatter.format(test_msg);

    std::cout << "===== 测试2: 自定义格式(简化版) =====" << std::endl;
    LzcLog::LogFormatter custom_formatter("[%d{%Y-%m-%d %H:%M:%S}][%p] %m %% 完成\n"); // 包含%%转义
    std::cout << custom_formatter.format(test_msg);

    std::cout << "===== 测试3: 边界场景(无效key+未闭合子项) =====" << std::endl;
    LzcLog::LogFormatter edge_formatter("[%d{YYYY-MM-DD][%x][%t]%T%m\n"); // %x是无效key，%d子项无闭合(故意写漏})
    std::cout << edge_formatter.format(test_msg);
}

void TestLogSink()
{
    // 1. 测试 标准输出（直接看终端）
    auto stdout_sink = LzcLog::SinkFactory::CreateSink<LzcLog::StdoutSink>();
    std::string log1 = "标准输出测试成功！\n";
    stdout_sink->Log(log1.data(), log1.size());

    // 2. 测试 指定文件写入（看 ./logs/test.log）
    auto file_sink = LzcLog::SinkFactory::CreateSink<LzcLog::FileSink>("./test.log");
    std::string log2 = "文件写入测试成功！";
    file_sink->Log(log2.data(), log2.size());

    // 3. 测试 按大小滚动（阈值100字节，写2条100字节日志，触发滚动）
    auto roll_sink = LzcLog::SinkFactory::CreateSink<LzcLog::RollBySizeSink>("./roll_by_size-", 100);
    std::string log3 = "滚动测试日志：" + std::string(80, 'a') + "\n"; // 约100字节
    roll_sink->Log(log3.data(), log3.size());
    roll_sink->Log(log3.data(), log3.size()); // 第2条触发滚动，写入新文件
}

void TestSyncLogger()
{
    auto builder = std::make_unique<LzcLog::LocalLoggerBuilder>();
    builder->BuildLoggerType(LzcLog::LoggerType::LOGGER_SYNC); // 同步日志器
    builder->BuildLoggerName("sync_logger");
    builder->BuildLoggerMinLevel(LzcLog::LogLevel::Value::WARNING);
    builder->BuildLoggerFormatter(); // 默认格式
    builder->BuildLoggerSink<LzcLog::StdoutSink>();
    builder->BuildLoggerSink<LzcLog::FileSink>("./logfile/sync.log");
    builder->BuildLoggerSink<LzcLog::RollBySizeSink>("./logfile/roll_by_size-", 1024*1024);

    auto sync_logger = builder->Build();
    
    sync_logger->DEBUG(__FILE__, __LINE__, "%s", "测试日志");
    sync_logger->INFO(__FILE__, __LINE__, "%s", "测试日志");
    sync_logger->WARNING(__FILE__, __LINE__, "%s", "测试日志");
    sync_logger->ERROR(__FILE__, __LINE__, "%s", "测试日志");
    sync_logger->FATAL(__FILE__, __LINE__, "%s", "测试日志");
    size_t count = 0;
    while(count < 50000)
    {
        sync_logger->FATAL(__FILE__, __LINE__, "%s%d", "测试日志", count);
        ++count;
    }
}

void TestBuffer()
{
    // 按文本方式读, 读到'\0'可能会结束, 所以按照二进制的方式读
    std::ifstream in("./logfile/test.log", std::ios::binary);
    if(!in.is_open()) { return; }
    in.seekg(0, in.end);        // 将文件读指针移动到文件末尾
    int file_size = in.tellg(); // 获取文件的字节数
    in.seekg(0, in.beg); // 将指针移回文件开头
    std::string body;
    body.resize(file_size);
    in.read(body.data(),file_size); // C++17后 data() 可返回 char*（非const） 或者 &body[0]
    in.close();

    LzcLog::Buffer buffer;
    for(int i = 0; i < body.size(); ++i)
    {
        buffer.Push(&body[i], 1);
    }
    std::ofstream out("./logfile/tmp.log", std::ios::binary);
    size_t size = buffer.ReadAbleSize();
    for(int i = 0; i < size; ++i)
    {
        out.write(buffer.Begin(), 1);
        buffer.MoveReaderIdx(1);
    }
    out.close();
}

void TestAsyncLogger()
{
    auto builder = std::make_unique<LzcLog::LocalLoggerBuilder>();
    builder->BuildLoggerType(LzcLog::LoggerType::LOGGER_ASYNC); // 异步日志器
    builder->BuildLoggerName("async_logger");
    builder->BuildLoggerMinLevel(LzcLog::LogLevel::Value::WARNING);
    builder->BuildLoggerFormatter(); // 默认格式
    // builder->BuildUnSafeAsync(); // 扩容
    builder->BuildLoggerSink<LzcLog::StdoutSink>();
    builder->BuildLoggerSink<LzcLog::FileSink>("./logfile/async.log");

    auto async_logger = builder->Build();
    
    async_logger->DEBUG(__FILE__, __LINE__, "%s", "测试日志");
    async_logger->INFO(__FILE__, __LINE__, "%s", "测试日志");
    async_logger->WARNING(__FILE__, __LINE__, "%s", "测试日志");
    async_logger->ERROR(__FILE__, __LINE__, "%s", "测试日志");
    async_logger->FATAL(__FILE__, __LINE__, "%s", "测试日志");
    size_t count = 0;
    while(count < 50000)
    {
        async_logger->FATAL(__FILE__, __LINE__, "%s%d", "测试日志", count);
        ++count;
    }
}

void _TestGlobalLoggerBuilder()
{
    auto builder = std::make_unique<LzcLog::GlobalLoggerBuilder>();
    builder->BuildLoggerType(LzcLog::LoggerType::LOGGER_ASYNC); // 异步日志器
    builder->BuildLoggerName("async_logger");
    builder->BuildLoggerMinLevel(LzcLog::LogLevel::Value::WARNING);
    builder->BuildLoggerFormatter(); // 默认格式
    // builder->BuildUnSafeAsync(); // 扩容
    builder->BuildLoggerSink<LzcLog::StdoutSink>();
    builder->BuildLoggerSink<LzcLog::FileSink>("./logfile/async.log");
    builder->Build();
}

void TestGlobalLoggerBuilder()
{
    _TestGlobalLoggerBuilder(); // 创建全局的日志器
    // 可以在其他地方，调用全局的日志器
    auto async_logger = LzcLog::LoggerManager::GetInstance().GetLogger("async_logger");
    async_logger->DEBUG(__FILE__, __LINE__, "%s", "测试日志");
    async_logger->INFO(__FILE__, __LINE__, "%s", "测试日志");
    async_logger->WARNING(__FILE__, __LINE__, "%s", "测试日志");
    async_logger->ERROR(__FILE__, __LINE__, "%s", "测试日志");
    async_logger->FATAL(__FILE__, __LINE__, "%s", "测试日志");
    size_t count = 0;
    while(count < 50000)
    {
        async_logger->FATAL(__FILE__, __LINE__, "%s%d", "测试日志", count);
        ++count;
    }
}

void TestLzcLog() {
    auto builder = std::make_unique<LzcLog::LocalLoggerBuilder>();
    builder->BuildLoggerType(LzcLog::LoggerType::LOGGER_ASYNC); // 异步日志器
    builder->BuildLoggerName("async_logger");
    builder->BuildLoggerMinLevel(LzcLog::LogLevel::Value::WARNING);
    builder->BuildLoggerFormatter(); // 默认格式
    // builder->BuildUnSafeAsync(); // 扩容
    builder->BuildLoggerSink<LzcLog::FileSink>("./logfile/async.log"); // 文件打印

    auto async_logger = builder->Build();
    
    async_logger->LOG_DEBUG("%s", "测试日志");
    async_logger->LOG_INFO("%s", "测试日志");
    async_logger->LOG_WARNING("%s", "测试日志");
    async_logger->LOG_ERROR("%s", "测试日志");
    async_logger->LOG_FATAL("%s", "测试日志");
    size_t count = 0;
    while(count < 50000)
    {
        async_logger->LOG_FATAL("%s%d", "测试日志", count);
        ++count;
    }

    // 标准输出打印
    LOGD("%s", "测试日志");
    LOGI("%s", "测试日志");
    LOGW("%s", "测试日志");
    LOGE("%s", "测试日志");
    LOGF("%s", "测试日志");
}

void _TestLog()
{
    std::unique_ptr<LzcLog::LoggerBuilder> builder = std::make_unique<LzcLog::GlobalLoggerBuilder>();
    builder->BuildLoggerType(LzcLog::LoggerType::LOGGER_ASYNC); // 异步日志器
    builder->BuildLoggerName("async_logger");
    builder->BuildLoggerMinLevel(LzcLog::LogLevel::Value::WARNING);
    builder->BuildLoggerFormatter(); // 默认格式
    // builder->BuildUnSafeAsync(); // 扩容
    builder->BuildLoggerSink<LzcLog::StdoutSink>();
    builder->BuildLoggerSink<LzcLog::FileSink>("./logfile/async.log");
    builder->BuildLoggerSink<LzcLog::RollBySizeSink>("./logfile/roll-async-by-size-", 1024*1024);
    builder->Build();
}

void TestLog(const std::string& name)
{
    _TestLog();
    LOGI("%s", "测试开始"); // 同步，立即输出
    LzcLog::Logger::ptr async_logger = LzcLog::GetLogger(name);
    async_logger->LOG_DEBUG("%s", "测试日志"); // 异步 放缓冲区了
    async_logger->LOG_INFO("%s", "测试日志"); // 异步
    async_logger->LOG_WARNING("%s", "测试日志"); // 异步
    async_logger->LOG_ERROR("%s", "测试日志"); // 异步
    async_logger->LOG_FATAL("%s", "测试日志"); // 异步
    LOGI("%s", "测试结束"); // 同步，立即输出
}

int main()
{
    TestLog("async_logger");
    return 0;
}